import { type SetStateAction, useEffect, useRef, useState } from 'react';
import type { DataSourceArray } from 'photoswipe';
import useGallery from '@/hooks/useGallery';
import { useQuery } from '@tanstack/react-query';
import { queryFile } from '@/services/api';
import useToast from '@/hooks/useToast';
import type { TMetadata } from '@/types';
import type { IClientFile } from '@/interfaces';
import clipboard from 'clipboard';
import { flushSync } from 'react-dom';

export default function useContentLayer({
  dep,
  metadata,
  selectors = '.content-layer',
}: {
  dep: any;
  metadata: TMetadata;
  selectors?: string;
}) {
  const { show } = useToast();
  const [dataSource, setDataSource] = useState<DataSourceArray | any[]>([]);
  const galleryRef = useGallery({ dataSource });
  const [fileId, setFileId] = useState<string | null>(null);
  const queryFileQuery = useQuery(
    ['/file', fileId],
    async (context) => {
      return (await queryFile({
        id: context.queryKey[1] + '',
      })) as IClientFile;
    },
    {
      enabled: false,
    },
  );
  const isInit = useRef(false);

  useEffect(() => {
    const contents: Element[] = [];
    const contentFns: EventListenerOrEventListenerObject[] = [];

    function handleContentLayer(nodes: NodeListOf<Element>) {
      for (let i = 0; i < nodes.length; i++) {
        const el = nodes[i];

        const fn = (e: Event) => {
          const target = e.target as Element | null;
          if (!target) {
            return;
          }

          if (
            target.nodeName === 'I' &&
            target.classList.contains('yw-code-copy-btn')
          ) {
            handleCodeBlockCopy(target);
          } else if (
            target.nodeName === 'IMG' &&
            target.classList.contains('image')
          ) {
            handleImageLink(target);
          } else if (target.nodeName === 'SPAN' || target.nodeName === 'I') {
            if (
              target.parentElement &&
              target.parentElement.nodeName === 'A' &&
              target.parentElement.classList.contains('file')
            ) {
              handleAttachmentLink(target.parentElement);
            }
          }
        };

        contents.push(el);
        contentFns.push(fn);
        el.addEventListener('click', fn);
      }
    }

    function handleCodeBlockCopy(el: Element) {
      if (!clipboard.isSupported()) {
        show({
          type: 'DANGER',
          message: '复制失败，当前环境不支持',
        });

        setTimeout(() => {
          show({
            type: 'PRIMARY',
            message: '请尝试手动复制',
          });
        }, 1000);
        return;
      }

      const parentElement = el.parentElement;
      if (!parentElement) {
        return;
      }

      const divElement = parentElement.parentElement;
      if (!divElement) {
        return;
      }

      const element = divElement.querySelector('pre code');
      if (!element) {
        return;
      }

      try {
        clipboard.copy(element);
        show({
          type: 'SUCCESS',
          message: '复制完成',
        });
      } catch (e) {
        show({
          type: 'DANGER',
          message: e,
        });

        setTimeout(() => {
          show({
            type: 'PRIMARY',
            message: '请尝试手动复制',
          });
        }, 1000);
      }
    }

    function handleImageLink(target: Element) {
      const parentElement = target.parentElement;
      if (parentElement && parentElement.nodeName === 'A') {
        return;
      }

      const nodes = document.querySelectorAll(`${selectors} img.image`);
      const tempArr: SetStateAction<DataSourceArray> = [];
      let _index;
      for (let i = 0; i < nodes.length; i++) {
        const el = nodes[i];
        const index = i;
        const src = el.getAttribute('src');
        let width = el.getAttribute('width');
        let height = el.getAttribute('height');
        const alt = el.getAttribute('alt') || `img${index + 1}`;

        if (src && (!width || !height)) {
          const { width: _width, height: _height } = el.getBoundingClientRect();
          if (_width > 0 && _height > 0) {
            width = _width + '';
            height = _height + '';
          }
        }

        if (!src || !width || !height) {
          return;
        } else {
          tempArr.push({
            element: el as HTMLElement,
            src,
            width: parseFloat(width),
            height: parseFloat(height),
            alt,
            msrc: src,
          });

          if (src === target.getAttribute('src')) {
            _index = index;
          }
        }
      }

      if (typeof _index === 'number') {
        galleryRef.current?.loadAndOpen(_index, tempArr);
      }
    }

    function handleAttachmentLink(el: Element) {
      const fid = el.getAttribute('data-fid');
      if (!fid) {
        show({
          type: 'DANGER',
          message: '文件不存在',
        });
        return;
      }

      flushSync(() => {
        setFileId(fid);
      });

      queryFileQuery
        .refetch({
          throwOnError: true,
        })
        .then((response) => {
          const data = response.data;
          if (!data) {
            show({
              type: 'DANGER',
              message: '下载失败，请尝试重新下载',
            });
            return;
          }

          download(
            metadata.env.APP_OSS_SERVER + data.urls.default,
            data.originalName || 'file',
          );
        })
        .catch((reason) => {
          show({
            type: 'DANGER',
            message: reason,
          });
        });
    }

    function download(href: string, download: string) {
      fetch(href)
        .then((res) => res.blob())
        .then((res) => {
          const aElement = document.createElement('a');
          aElement.style.display = 'none';
          aElement.setAttribute('download', download);
          const href = URL.createObjectURL(res);
          aElement.href = href;
          aElement.setAttribute('target', '_blank');
          document.body.appendChild(aElement);
          aElement.click();
          setTimeout(() => {
            URL.revokeObjectURL(href);
            document.body.removeChild(aElement);
          }, 1000);
        })
        .then((value) => {
          show({
            type: 'SUCCESS',
            message: '开始下载',
          });
        })
        .catch((reason) => {
          show({
            type: 'DANGER',
            message: reason,
          });
        });
    }

    const isInitValue = isInit.current;
    if (!!dep && selectors && !isInitValue) {
      handleContentLayer(document.querySelectorAll(selectors));
      isInit.current = true;
    }

    return () => {
      if (isInitValue) {
        contents.forEach((el, index) => {
          el.removeEventListener('click', contentFns[index]);
        });
      }
    };
  }, [dep, selectors]);
}
